/**
 *
 *  License: http://www.apache.org/licenses/LICENSE-2.0
 *  Home page: https://gitee.com/linlurui/service-abc
 *  Note: to build on java, include the jdk1.8+ compiler symbol (and yes,
 *  I know the difference between language and runtime versions; this is a compromise).
 * @author linlurui
 * @Date Date: 2019-02-10
 */


package abc.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xbill.DNS.Address;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.net.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NetworkUtil {

    private static final Logger log = LoggerFactory.getLogger( NetworkUtil.class );
    //服务器 公网IP
    public static String publicIp;
    //服务器 内网IP
    public static String serversIp;

    /**
     * @author: linlurui
     * @date: 2021/3/18
     * @description:获取服务Ip详情
     */
    public static Map<String, String> getIpInfo() {
        String serverIp = null;
        String serverPort = null;
        Map<String, String> ipInfo = new HashMap();
        try {
            MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
            Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                    Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
            serverIp = InetAddress.getLocalHost().getHostAddress();
            serverPort = objectNames.iterator().next().getKeyProperty("port");
            ipInfo.put(serverIp, serverPort);
        } catch (Exception e) {
            log.error("Failed to get current service IP : ", e);
        }
        return ipInfo;
    }



    /**
     * @author: linlurui
     * @date: 2021/3/17
     * @description:获取当前机器的端口号
     */
    public static String getLocalPort() {
        String serverPort = "0";
        try {
            MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
            Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                    Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
            Iterator<ObjectName> item = objectNames.iterator();
            if(!item.hasNext()) {
                return serverPort;
            }
            ObjectName next = objectNames.iterator().next();
            if(next == null) {
                return serverPort;
            }
            serverPort = objectNames.iterator().next().getKeyProperty("port");
            ExceptionUtil.isBlank(serverPort, "当前服务端口获取失败！");
            return serverPort;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return serverPort;
    }


    /**
     * @author: linlurui
     * @date: 2021/3/18
     * @description:获取公网IP+端口
     */
    public static String getPublicIp() {
        try {
            if (StringUtil.isEmpty(publicIp)) {
                String ip = publicIp();
                ExceptionUtil.isBlank(ip, "当前服务(公网IP)获取失败！");
                String port = getLocalPort();
                ExceptionUtil.isBlank(port, "当前服务(端口号)获取失败！");
                StringBuffer result = new StringBuffer(ip);
                result.append(":");
                result.append(port);
                publicIp = result.toString();
                log.info("Get public ip:" + ip);
            }
        } catch (Exception e) {
            log.error("Failed to get current service Ip : " + e.getMessage());
        }
        return publicIp;
    }

    /**
     * @author: linlurui
     * @date: 2021/9/12
     * @description:公网IP
     */
    public static String publicIp() {
        String ip = null;
        // 第一种方式
        try {
            ip = getNowIP1();
            if (!StringUtil.isEmpty(ip)) {
                ip.trim();
                return ip;
            }
            // 第二种方式
            ip = getNowIP2();
            if (!StringUtil.isEmpty(ip)) {
                ip.trim();
                return ip;
            }

            // 第三种方式
            ip = getNowIP3();
            if (!StringUtil.isEmpty(ip)) {
                ip.trim();
                return ip;
            }

            // 第四种方式
            ip = getNowIP4();
            if (!StringUtil.isEmpty(ip)) {
                ip.trim();
                return ip;
            }
        } catch (Exception e) {
            log.error("Get public Ip Failed!");
        }
        return ip;
    }

    /**
     * @author: linlurui
     * @date: 2021/9/12
     * @description:获取公网IP方法1
     */
    private static String getNowIP1() throws IOException {
        try {
            String ip = null;
            BufferedReader br = null;
            try {
                URL url = new URL("https://v6r.ipip.net/?format=callback");
                br = new BufferedReader(new InputStreamReader(url.openStream()));
                String s = "";
                StringBuffer sb = new StringBuffer("");
                String webContent = "";
                while ((s = br.readLine()) != null) {
                    sb.append(s + "\r\n");
                }
                webContent = sb.toString();
                int start = webContent.indexOf("(") + 2;
                int end = webContent.indexOf(")") - 1;
                webContent = webContent.substring(start, end);
                ip = webContent;
            } finally {
                if (br != null)
                    br.close();
            }
            if (StringUtil.isEmpty(ip)) {
                throw new RuntimeException();
            }
            return ip;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @author: linlurui
     * @date: 2021/9/12
     * @description:获取公网IP方法2
     */
    private static String getNowIP2() {
        try {
            String ip = null;
            String chinaz = "http://ip.chinaz.com";
            StringBuilder inputLine = new StringBuilder();
            String read = "";
            URL url = null;
            HttpURLConnection urlConnection = null;
            BufferedReader in = null;
            try {
                url = new URL(chinaz);
                urlConnection = (HttpURLConnection) url.openConnection();
                in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
                while ((read = in.readLine()) != null) {
                    inputLine.append(read + "\r\n");
                }
                Pattern p = Pattern.compile("\\<dd class\\=\"fz24\">(.*?)\\<\\/dd>");
                Matcher m = p.matcher(inputLine.toString());
                if (m.find()) {
                    String ipstr = m.group(1);
                    ip = ipstr;
                }
            } finally {
                if (in != null) {
                    in.close();
                }
            }
            if (StringUtil.isEmpty(ip)) {
                throw new RuntimeException();
            }
            return ip;
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * @author: linlurui
     * @date: 2021/9/12
     * @description:获取公网IP方法2
     */
    private static String getNowIP3() throws IOException {
        try {
            String ip = null;
            String objWebURL = "https://ip.900cha.com/";
            BufferedReader br = null;
            try {
                URL url = new URL(objWebURL);
                br = new BufferedReader(new InputStreamReader(url.openStream()));
                String s = "";
                String webContent = "";
                while ((s = br.readLine()) != null) {
                    if (s.indexOf("我的IP:") != -1) {
                        ip = s.substring(s.indexOf(":") + 1);
                        break;
                    }
                }
            } finally {
                if (br != null)
                    br.close();
            }
            if (StringUtil.isEmpty(ip)) {
                throw new RuntimeException();
            }
            return ip;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @author: linlurui
     * @date: 2021/9/12
     * @description:获取公网IP方法4
     */
    private static String getNowIP4() throws IOException {
        try {
            String ip = null;
            String objWebURL = "https://bajiu.cn/ip/";
            BufferedReader br = null;
            try {
                URL url = new URL(objWebURL);
                br = new BufferedReader(new InputStreamReader(url.openStream()));
                String s = "";
                String webContent = "";
                while ((s = br.readLine()) != null) {
                    if (s.indexOf("互联网IP") != -1) {
                        ip = s.substring(s.indexOf("'") + 1, s.lastIndexOf("'"));
                        break;
                    }
                }
            } finally {
                if (br != null)
                    br.close();
            }
            if (StringUtil.isEmpty(ip)) {
                throw new RuntimeException();
            }
            return ip;
        } catch (Exception e) {
            return null;
        }
    }

    public static String getDomain(String ip) throws UnknownHostException {
        return Address.getHostName(InetAddress.getByName(ip));
    }

    public static InetAddress[] getInetAddress(String domain) throws UnknownHostException {
        InetAddress[] addresses = InetAddress.getAllByName(domain);

        return addresses;
    }

    /**
     * 获得服务器内网IP
     * @return 内网IP
     */
    public static String getIntranetIp(){
        try{
            return InetAddress.getLocalHost().getHostAddress();
        } catch(Exception e){
            log.error(e.getMessage(), e);
            return "unknown-ip";
        }
    }

    /**
     * 获得服务器外网IP
     * @return 外网IP
     */
    public static String getInternetIp(){
        try{
            Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            Enumeration<InetAddress> addrs;
            while (networks.hasMoreElements())
            {
                addrs = networks.nextElement().getInetAddresses();
                while (addrs.hasMoreElements())
                {
                    ip = addrs.nextElement();
                    if (ip != null
                            && ip instanceof Inet4Address
                            && ip.isSiteLocalAddress()
                            && !ip.getHostAddress().equals(publicIp))
                    {
                        return ip.getHostAddress();
                    }
                }
            }

            // 如果没有外网IP，就返回内网IP
            return publicIp;
        } catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}
